package com.remac.framework.mybatisplus.extensions.enhance.support;

import com.baomidou.mybatisplus.core.MybatisConfiguration;
import com.remac.framework.mybatisplus.extensions.enhance.IMybatisPlusEnhancer;
import com.remac.framework.mybatisplus.extensions.typehandler.IGenericTypeHandler;
import com.remac.framework.mybatisplus.extensions.typehandler.json.AbstractGenericJsonTypeHandler;
import com.remac.framework.mybatisplus.extensions.typehandler.json.AbstractJsonObjectTypeHandler;
import org.apache.ibatis.mapping.ResultMap;
import org.apache.ibatis.type.TypeHandler;
import org.apache.ibatis.type.TypeHandlerRegistry;
import org.apache.ibatis.type.UnknownTypeHandler;
import org.springframework.util.ReflectionUtils;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.lang.reflect.Type;
import java.util.Collection;
import java.util.Objects;

/**
 * @author Ye Junhui
 * @since 2024/4/26
 */
public class JsonUnknownTypeHandlerMybatisPlusEnhancer implements IMybatisPlusEnhancer {
    @Override
    public void enhance(MybatisConfiguration mybatisConfiguration) {
        TypeHandlerRegistry typeHandlerRegistry = mybatisConfiguration.getTypeHandlerRegistry();
        UnknownTypeHandler unknownTypeHandler = (UnknownTypeHandler) typeHandlerRegistry.getUnknownTypeHandler();
        try {
            Field field = UnknownTypeHandler.class.getDeclaredField("OBJECT_TYPE_HANDLER");
            field.setAccessible(true);
            Field modifiers = field.getClass().getDeclaredField("modifiers");
            modifiers.setAccessible(true);
            modifiers.setInt(field, field.getModifiers() & ~Modifier.FINAL);
            Collection resultMaps = (Collection) mybatisConfiguration.getResultMaps();
            resultMaps.forEach(resultMapObj -> {
                if (!(resultMapObj instanceof ResultMap)) {
                    return;
                }
                ResultMap resultMap = (ResultMap) resultMapObj;

                //映射结果
                resultMap.getResultMappings().forEach(resultMapping -> {
                    //字段类型处理器
                    TypeHandler<?> typeHandler = resultMapping.getTypeHandler();
                    if (Objects.isNull(typeHandler) || !(typeHandler instanceof AbstractGenericJsonTypeHandler)) {
                        return;
                    }

                    //json处理器
                    AbstractGenericJsonTypeHandler<?> genericJsonTypeHandler = (AbstractGenericJsonTypeHandler<?>) typeHandler;
                    AbstractJsonObjectTypeHandler writeHandler = genericJsonTypeHandler.getWriteHandler();
                    try {
                        field.set(unknownTypeHandler, writeHandler);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                });
            });
        } catch (Exception e) {

        }
    }
}
